#include "preHeader.h"
#include "Guild/GuildMgr.h"
#include "Session/C2GuildPacketHandler.h"
#include "Session/S2GuildPacketHandler.h"
#include "Session/GameServerMgr.h"
#include "Game/TransMgr.h"
#include "Game/PacketDispatcher.h"

int S2GuildPacketHandler::HandleUpdateGameServer(GuildMgr *mgr, INetPacket &pck)
{
	for (auto& [guildId, pGuild] : mgr->GetGuilds()) {
		pGuild->PullAllGuildMemberFightValues2Rank();
	}
	return SessionHandleSuccess;
}

int S2GuildPacketHandler::HandleUpdateCharacterInfo(GuildMgr *mgr, INetPacket &pck)
{
	uint32 playerId, guildId;
	pck >> playerId >> guildId;
	CBitMask& bitMask = mgr->sCharUpdateInfoBitMask;
	bitMask.Read(pck);
	if (bitMask.IsDirty((int)CharUpdateInfo::Type::FightValue)) {
		auto pGuild = mgr->GetGuild4Player(playerId, guildId);
		if (pGuild != NULL) {
			pGuild->PullGuildMemberFightValue2Rank(playerId);
		}
	}
	return SessionHandleSuccess;
}

int C2GuildPacketHandler::HandleGuildGetList(GuildMgr *mgr, INetPacket &pck, uint32 uid)
{
	uint32 startIndex, getCountMax;
	pck >> startIndex >> getCountMax;
	Coroutine::Spawn([=](Coroutine::YieldContext& ctx) {
		auto errCode = mgr->HandleGetGuildList(ctx, uid, startIndex, getCountMax);
		if (errCode != CommonSuccess) {
			sTransMgr.SendError2ClientSafe(uid, errCode);
		}
	});
	return SessionHandleSuccess;
}

int C2GuildPacketHandler::HandleGuildGetInfo(GuildMgr *mgr, INetPacket &pck, uint32 uid)
{
	uint32 guildId;
	pck >> guildId;
	Coroutine::Spawn([=](Coroutine::YieldContext& ctx) {
		auto errCode = mgr->HandleGetGuildInfo(ctx, guildId, uid);
		if (errCode != CommonSuccess) {
			sTransMgr.SendError2ClientSafe(uid, errCode);
		}
	});
	return SessionHandleSuccess;
}

int C2GuildPacketHandler::HandleGuildGetMember(GuildMgr *mgr, INetPacket &pck, uint32 uid)
{
	uint32 guildId;
	pck >> guildId;
	Coroutine::Spawn([=](Coroutine::YieldContext& ctx) {
		auto errCode = mgr->HandleGetGuildMember(ctx, guildId, uid);
		if (errCode != CommonSuccess) {
			sTransMgr.SendError2ClientSafe(uid, errCode);
		}
	});
	return SessionHandleSuccess;
}

int S2GuildPacketHandler::HandleGuildGetApply(GuildMgr *mgr, INetPacket &pck)
{
	uint32 guildId, playerId;
	pck >> guildId >> playerId;
	Coroutine::Spawn([=](Coroutine::YieldContext& ctx) {
		auto errCode = mgr->HandleGetGuildApply(ctx, guildId, playerId);
		if (errCode != CommonSuccess) {
			sTransMgr.SendError2ClientSafe(playerId, errCode);
		}
	});
	return SessionHandleSuccess;
}

int S2GuildPacketHandler::HandlePullGuildInfos(GuildMgr *mgr, INetPacket &pck, const RPCActor::RequestMetaInfo &info)
{
	uint8 replyType;
	uint32 flags, types;
	pck >> replyType >> flags >> types;
	NetPacket rpcRespPck(SGX_RPC_INVOKE_RESP);
	size_t anchor = 0, num = 0;
	if ((flags & (u32)PullValueFlag::NonDict) == 0) {
		anchor = rpcRespPck.Placeholder<u16>(0);
	}
	while (pck.IsReadableEmpty()) {
		uint32 infoKey, guildId;
		if ((flags & (u32)PullValueFlag::ExtraKey) == 0) {
			pck >> guildId; infoKey = guildId;
		} else {
			pck >> infoKey >> guildId;
		}
		auto pGuild = mgr->GetGuild(guildId);
		if (pGuild == NULL) {
			continue;
		}
		NetBuffer buffer;
		if ((types & (u32)GuildValueType::Key) != 0) {
			buffer << guildId;
		}
		if ((types & (u32)GuildValueType::Name) != 0) {
			buffer << pGuild->GetGuildName();
		}
		if ((types & (u32)GuildValueType::Level) != 0) {
			buffer << pGuild->GetGuildInformation().level;
		}
		if ((flags & (u32)PullValueFlag::NonDict) == 0) {
			rpcRespPck << infoKey << buffer.CastBufferStringView();
		} else {
			rpcRespPck.Append(buffer.GetBuffer(), buffer.GetTotalSize());
		}
		++num;
	}
	if ((flags & (u32)PullValueFlag::NonDict) == 0) {
		rpcRespPck.Put(anchor, (u16)num);
	}
	sPacketDispatcher.RunS2SRPCReply((SocialRPCReply)replyType, rpcRespPck, info.sn);
	return SessionHandleSuccess;
}

int S2GuildPacketHandler::HandleGetAllGuilds(GuildMgr *mgr, INetPacket &pck)
{
	NetPacket resp(SGX_PUSH_ALL_GUILDS);
	for (auto&[Id, pGuild] : mgr->GetGuilds()) {
		resp << Id;
	}
	sGameServerMgr.SendPacket2GS(resp);
	return SessionHandleSuccess;
}

int S2GuildPacketHandler::HandleGetAllCharacterGuilds(GuildMgr *mgr, INetPacket &pck)
{
	NetPacket resp(SGX_PUSH_CHARACTER_GUILDS);
	size_t i = 0;
	for (auto&[Id, pGuild] : mgr->GetGuilds()) {
		for (auto&[playerId, guildMember] : pGuild->GetGuildMembers()) {
			resp << guildMember.playerId << guildMember.guildId
				<< guildMember.guildTitle << pGuild->GetGuildName();
			if (++i >= 2500) {
				sGameServerMgr.SendPacket2GS(resp);
				resp.Clear();
				i = 0;
			}
		}
	}
	if (i > 0) {
		sGameServerMgr.SendPacket2GS(resp);
	}
	return SessionHandleSuccess;
}

int S2GuildPacketHandler::HandleTryGuildCreate(GuildMgr *mgr, INetPacket &pck, const RPCActor::RequestMetaInfo &info)
{
	INetPacket rpcRespPck(SGX_RPC_INVOKE_RESP);
	uint32 guildId, playerId;
	pck >> guildId >> playerId;
	auto errCode = mgr->HandleTryGuildCreate(guildId, playerId);
	rpcRespPck << (int32)errCode;
	sGameServerMgr.RPCReply2GS(rpcRespPck, info.sn);
	return SessionHandleSuccess;
}

int S2GuildPacketHandler::HandleGuildCreate(GuildMgr *mgr, INetPacket &pck, const RPCActor::RequestMetaInfo &info)
{
	INetPacket rpcRespPck(SGX_RPC_INVOKE_RESP);
	uint32 gsId, guildId, playerId, newGuildId;
	std::string_view newGuildName;
	pck >> gsId >> guildId >> playerId >> newGuildId >> newGuildName;
	auto errCode = mgr->HandleGuildCreate(gsId, guildId, playerId, newGuildId, newGuildName);
	rpcRespPck << (int32)errCode;
	sGameServerMgr.RPCReply2GS(rpcRespPck, info.sn);
	return SessionHandleSuccess;
}

int S2GuildPacketHandler::HandleGuildInvite(GuildMgr *mgr, INetPacket &pck)
{
	uint32 guildId, playerId, tgtGuildId, tgtPlayerId;
	pck >> guildId >> playerId >> tgtGuildId >> tgtPlayerId;
	Coroutine::Spawn([=](Coroutine::YieldContext& ctx) {
		auto errCode = mgr->HandleGuildInvite(ctx, guildId, playerId, tgtGuildId, tgtPlayerId);
		if (errCode != CommonSuccess) {
			sTransMgr.SendError2ClientSafe(playerId, errCode);
		}
	});
	return SessionHandleSuccess;
}

int S2GuildPacketHandler::HandleGuildInviteResp(GuildMgr *mgr, INetPacket &pck)
{
	uint32 guildId, playerId, tgtGuildId;
	bool isAgree;
	pck >> guildId >> playerId >> tgtGuildId >> isAgree;
	Coroutine::Spawn([=](Coroutine::YieldContext& ctx) {
		auto errCode = mgr->HandleGuildInviteResp(ctx, guildId, playerId, tgtGuildId, isAgree);
		if (errCode != CommonSuccess) {
			sTransMgr.SendError2ClientSafe(playerId, errCode);
		}
	});
	return SessionHandleSuccess;
}

int S2GuildPacketHandler::HandleGuildApply(GuildMgr *mgr, INetPacket &pck)
{
	uint32 guildId, playerId, tgtGuildId;
	pck >> guildId >> playerId >> tgtGuildId;
	Coroutine::Spawn([=](Coroutine::YieldContext& ctx) {
		auto errCode = mgr->HandleGuildApply(ctx, guildId, playerId, tgtGuildId);
		if (errCode != CommonSuccess) {
			sTransMgr.SendError2ClientSafe(playerId, errCode);
		}
	});
	return SessionHandleSuccess;
}

int S2GuildPacketHandler::HandleGuildApplyResp(GuildMgr *mgr, INetPacket &pck)
{
	uint32 guildId, playerId, tgtGuildId, tgtApplicantId;
	bool isAgree;
	pck >> guildId >> playerId >> tgtGuildId >> tgtApplicantId >> isAgree;
	Coroutine::Spawn([=](Coroutine::YieldContext& ctx) {
		auto errCode = mgr->HandleGuildApplyResp(ctx, guildId, playerId, tgtGuildId, tgtApplicantId, isAgree);
		if (errCode != CommonSuccess) {
			sTransMgr.SendError2ClientSafe(playerId, errCode);
		}
	});
	return SessionHandleSuccess;
}

int S2GuildPacketHandler::HandleGuildLeave(GuildMgr *mgr, INetPacket &pck)
{
	uint32 guildId, playerId;
	pck >> guildId >> playerId;
	Coroutine::Spawn([=](Coroutine::YieldContext& ctx) {
		auto errCode = mgr->HandleGuildLeave(ctx, guildId, playerId);
		if (errCode != CommonSuccess) {
			sTransMgr.SendError2ClientSafe(playerId, errCode);
		}
	});
	return SessionHandleSuccess;
}

int S2GuildPacketHandler::HandleGuildKick(GuildMgr *mgr, INetPacket &pck)
{
	uint32 guildId, playerId, tgtGuildId, tgtPlayerId;
	pck >> guildId >> playerId >> tgtGuildId >> tgtPlayerId;
	Coroutine::Spawn([=](Coroutine::YieldContext& ctx) {
		auto errCode = mgr->HandleGuildKick(ctx, guildId, playerId, tgtGuildId, tgtPlayerId);
		if (errCode != CommonSuccess) {
			sTransMgr.SendError2ClientSafe(playerId, errCode);
		}
	});
	return SessionHandleSuccess;
}

int S2GuildPacketHandler::HandleGuildRise(GuildMgr *mgr, INetPacket &pck)
{
	uint32 guildId, playerId, tgtGuildId, tgtPlayerId;
	int8 guildTitle;
	pck >> guildId >> playerId >> tgtGuildId >> tgtPlayerId >> guildTitle;
	Coroutine::Spawn([=](Coroutine::YieldContext& ctx) {
		auto errCode = mgr->HandleGuildRise(ctx, guildId, playerId, tgtGuildId, tgtPlayerId, guildTitle);
		if (errCode != CommonSuccess) {
			sTransMgr.SendError2ClientSafe(playerId, errCode);
		}
	});
	return SessionHandleSuccess;
}

int S2GuildPacketHandler::HandleGuildDisband(GuildMgr *mgr, INetPacket &pck, const RPCActor::RequestMetaInfo &info)
{
	uint32 guildId, playerId;
	pck >> guildId >> playerId;
	Coroutine::Spawn([=](Coroutine::YieldContext& ctx) {
		INetPacket rpcRespPck(SGX_RPC_INVOKE_RESP);
		uint32 finalGuildId = 0;
		auto errCode = mgr->HandleGuildDisband(ctx, guildId, playerId, finalGuildId);
		rpcRespPck << (int32)errCode << finalGuildId;
		sGameServerMgr.RPCReply2GS(rpcRespPck, info.sn);
	});
	return SessionHandleSuccess;
}
